home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / filesyst / xiafs / xiafspgm.8 / xiafspgm / xiafspgm-0.8.1 / mkboot.c < prev    next >
C/C++ Source or Header  |  1993-03-22  |  10KB  |  423 lines

  1. /*----------------------------------------------------------------------*
  2.  * mkboot.c                                *
  3.  *                                    *
  4.  * Copyright (C) Q. Frank Xia, 1993.  All rights reserved.              *
  5.  *                                                     *
  6.  * This software may be redistributed as per Linux copyright        *
  7.  *                                    *
  8.  -----------------------------------------------------------------------*/
  9.  
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <unistd.h>
  14. #include <fcntl.h>
  15. #include <string.h>
  16. #include <sys/stat.h>
  17. #include <sys/types.h>
  18. #include <stdarg.h>
  19. #include <linux/fs.h>
  20. #include <linux/xia_fs.h>
  21. #include <ctype.h>
  22. #include <getopt.h>
  23.  
  24. #include "bootsect.h"
  25.  
  26. #define    VERSION    "0.8"
  27.  
  28. #define FLOPPY     2
  29. #define IDE    3
  30. #define SCSI    8
  31.  
  32. struct partition_table {
  33.     u_char     who_care[8];
  34.     u_long     start_sect;
  35.     u_long     len_in_sect;
  36. };
  37.  
  38. union {
  39.     struct mast_text          mastsect;
  40.     struct boot_text          bootsect;
  41.     struct xiafs_super_block  supblock;
  42.     char   dummy[1024];
  43. } super_buf;
  44.  
  45. #define supb    super_buf.supblock
  46. #define master  super_buf.mastsect
  47. #define bsect    super_buf.bootsect
  48.  
  49. char   *pgm_name;        /* program name */
  50.  
  51. #define INST_SEC_BOOT    0
  52. #define INST_PRI_BOOT     1
  53. #define REST_PRI_BOOT    2
  54.  
  55. int     action;
  56. int     raw_boot;
  57. char     *os_name[4];
  58. int     os_part[4];
  59. int     os_nr;
  60. int     blk_dev;
  61. char     *blk_dev_name;
  62. char     *root_dev_name;
  63. int      part_dev;
  64. struct  partition_table   part_tab[4];
  65.  
  66. u_char     buf[512];
  67.  
  68. extern  u_char orgtext[];
  69. extern  u_char pritext[];
  70. extern  u_char sectext[];
  71.  
  72. void die(char * format, ...)
  73. {
  74.     va_list ap;
  75.  
  76.     va_start(ap, format);
  77.  
  78.     fprintf(stderr, "%s: ", pgm_name);
  79.     vfprintf(stderr, format, ap);
  80.     fprintf(stderr, "\n");
  81.  
  82.     va_end(ap);
  83.     exit(1);
  84. }
  85.  
  86. void usage()
  87. {
  88.     fprintf(stderr, "usage:  %s  -M disk_dev [-partition OS_name]\n", pgm_name);
  89.     fprintf(stderr, "        %s  [-fr root_dev] block_dev\n", pgm_name);
  90.     exit(1);
  91. }
  92.  
  93. int confirm()
  94. {
  95.     char c;
  96.  
  97.     fprintf(stderr, "Is this what you want to do ? [y/n] ");
  98.     fflush(stderr);
  99.     c=getchar();
  100.     if (c != 'y' && c != 'Y')
  101.         return 0;
  102.     getchar();
  103.     fprintf(stderr, "\nAre you sure ? [y/n] ");
  104.     fflush(stderr);
  105.     c=getchar();
  106.     fprintf(stderr, "\n");
  107.     if (c != 'y' && c != 'Y')
  108.         return 0;
  109.     return 1;
  110. }
  111.     
  112. void parse_pri(int argc, char *argv[])
  113. {
  114.     extern char * optarg;
  115.     int c;
  116.  
  117.     os_nr=0;
  118.     while ((c = getopt(argc, argv, "1:2:3:4:M:")) != EOF)
  119.         switch (c) {
  120.     case '1':
  121.     case '2':
  122.     case '3':
  123.     case '4': 
  124.         if (os_nr > 3)
  125.             die("Only 4 partitions are supported.");
  126.         os_name[os_nr] = optarg;
  127.         os_part[os_nr] = c - '0';
  128.         os_nr++;
  129.         break;
  130.     case 'M': 
  131.         if (os_nr > 0)
  132.             usage();
  133.         blk_dev_name = optarg;
  134.         break;
  135.     default : usage();
  136.     }
  137.     if ( os_nr == 0)
  138.         action = REST_PRI_BOOT;
  139.     else
  140.         action = INST_PRI_BOOT;
  141. }
  142.  
  143. void parse_sec(int argc, char *argv[])
  144. {
  145.     extern char * optarg;
  146.     extern int optind;
  147.     int c;
  148.  
  149.     raw_boot = 0;
  150.     root_dev_name = NULL;
  151.     while ((c = getopt(argc, argv, "f:r:")) != EOF)
  152.         switch(c) {
  153.     case 'f':
  154.     case 'r':
  155.         if (c == 'r')
  156.             raw_boot = 1;
  157.         root_dev_name = optarg;
  158.         break;
  159.     default: usage();
  160.     }
  161.     blk_dev_name = argv[optind];
  162.     if (!root_dev_name)
  163.         root_dev_name = blk_dev_name;
  164.     if (optind+1 < argc)
  165.         usage();
  166. }
  167.  
  168. void parse_arg(int argc, char *argv[])
  169. {
  170.     char *cp;
  171.  
  172.     if (argc < 2)
  173.         usage();
  174.     action = INST_SEC_BOOT;
  175.     cp = argv[1];
  176.     if (cp[0] == '-' && cp[1] == 'V' && !cp[2]) {
  177.         printf("mkboot, Version %s\n", VERSION);
  178.     exit(0);
  179.     }
  180.     if (cp[0] == '-' && cp[1] == 'M' && !cp[2])
  181.         parse_pri(argc, argv);
  182.     else
  183.         parse_sec(argc, argv);
  184. }
  185.     
  186. void get_part_tab(char * blk_dev_name)
  187. {
  188.     char * cp, * cp2;
  189.     char tmp;
  190.     int fd;
  191.     u_short signature;
  192.  
  193.     cp2 = cp = blk_dev_name + strlen(blk_dev_name) - 1;
  194.     while (*cp >= '0' && *cp <= '9') cp--;
  195.     if (cp == cp2)
  196.         die("bad block device name `%s'", blk_dev_name);
  197.     cp++;
  198.     tmp = *cp;
  199.     *cp = 0;
  200.     if ((fd = open(blk_dev_name, O_RDONLY)) < 0)
  201.         die("open device `%s' failed", blk_dev_name);
  202.     if (lseek(fd, 0x1be, SEEK_SET) != 0x1be || read(fd, part_tab, 64) != 64 
  203.     || read(fd, &signature, 2) != 2)
  204.         die("read device `%s' failed", blk_dev_name);
  205.     if (signature != 0xAA55)
  206.         die("bad partition table");
  207.     close(fd);
  208.     *cp = tmp;
  209. }
  210.     
  211.     
  212. int get_rdev(char * device)
  213. {
  214.     struct stat ds;
  215.     int major;
  216.  
  217.     stat(device, &ds);
  218.     if ( S_ISBLK(ds.st_mode) ) {
  219.         major = MAJOR(ds.st_rdev);
  220.     if (major == FLOPPY || major == IDE || major == SCSI)
  221.         return ds.st_rdev;
  222.     }
  223.     return 0;
  224. }
  225.  
  226.     
  227. void get_super_block() 
  228. {
  229.     if (!raw_boot) {                /* read in super block */
  230.         if (read(blk_dev, (void *)&super_buf, 1024) != 1024)
  231.         die("read device `%s' failed", blk_dev_name);    
  232.     if (supb.s_magic != _XIAFS_SUPER_MAGIC)
  233.         die("super magic mismatch");
  234.     }
  235.  
  236.     /* read in bootsect from Image */
  237.     if (read(0, (void *)&super_buf, 512) != 512 || bsect.boot_flag != 0xAA55)
  238.         die("bad kernel image");
  239.  
  240.     memcpy((void *)&super_buf, sectext, SECTEXTSIZE);
  241. }
  242.  
  243.  
  244. int put_image(u_long start_sect, int sectors)
  245. {
  246.     int tmp, i, count = 0;
  247.     u_char *cp;
  248.  
  249.     if (lseek(blk_dev, start_sect * 512, SEEK_SET) != start_sect * 512)
  250.         die("seek device `%s' failed", blk_dev_name);
  251.     while ((tmp = read(0, buf, 512)) > 0) {
  252.         count ++;
  253.     if (count > sectors)
  254.         die("not enought space");
  255.     if (tmp != 512) {
  256.         cp = tmp + (u_char *) buf;
  257.         for (i = tmp; i < 512; i++)
  258.             *cp++ = 0;
  259.     }
  260.     if (write(blk_dev, buf, 512) != 512)
  261.         die("write to device `%s' failed", blk_dev_name);
  262.     if (tmp != 512) {
  263.         count--;
  264.         goto put_image_done;
  265.     }
  266.     }
  267.  
  268. put_image_done:
  269.  
  270.     printf("kernel image size %d bytes\n", (count+1) * 512 + tmp);
  271.     return count + (tmp ? 1 : 0);
  272. }
  273.  
  274.  
  275. void put_super_block(u_long Istart_sector, int kern_sectors)
  276. {
  277.     u_long tmp;
  278.  
  279.     bsect.root_dev = get_rdev(root_dev_name);
  280.     bsect.Istart_sect = Istart_sector;
  281.  
  282.     tmp = (kern_sectors + 127) / 128 + 1;    /* rundup to 64KB + sys_seg */
  283.     tmp *= 0x1000;
  284.     bsect.end_seg = tmp;
  285.  
  286.     if (!raw_boot) {
  287.         tmp = 1 << (1 + supb.s_zone_shift);
  288.     supb.s_kernzones = (kern_sectors + tmp - 1) / tmp;
  289.     } 
  290.  
  291.     tmp = raw_boot ? 512 : 1024;
  292.     if (lseek(blk_dev, 0, SEEK_SET) != 0 || write(blk_dev, &super_buf, tmp) != tmp)
  293.         die("write device `%s' failed", blk_dev_name);    /* put super block */
  294. }
  295.  
  296.  
  297. void inst_sec_boot()
  298. {
  299.     int rdev, is_floppy;
  300.     u_long sect_reserved, sect_aligned, start_sect;
  301.  
  302.     if (!(rdev = get_rdev(blk_dev_name)))
  303.         die("bad block device name");
  304.     if ( MAJOR(rdev) == FLOPPY )
  305.         is_floppy = 1;
  306.     else 
  307.         is_floppy = 0;
  308.     rdev &= 0xf;
  309.     rdev--;
  310.     if (!is_floppy && ( rdev < 0 || rdev > 3) )
  311.         die("partition number not supported");
  312.     
  313.     if (!is_floppy)
  314.         get_part_tab(blk_dev_name);
  315.     if ( (blk_dev = open(blk_dev_name, O_RDWR)) < 0 )
  316.         die("open `%s' failed", blk_dev_name);
  317.     get_super_block();
  318.     if (raw_boot) {
  319.         if (is_floppy)
  320.         sect_reserved = 2400;
  321.     else {
  322.         sect_reserved = part_tab[rdev].len_in_sect;
  323.         sect_reserved -= 5;
  324.         sect_reserved &= ~127;
  325.     }
  326.     start_sect = 1;
  327.     } else {
  328.         if ( !supb.s_firstkernzone )
  329.         die("no space reserved for kernel image");
  330.         sect_aligned = (supb.s_nzones - supb.s_firstkernzone) << (1 + supb.s_zone_shift);
  331.     sect_aligned -= 4;
  332.     sect_aligned &= ~127;
  333.         sect_reserved = (supb.s_firstdatazone - supb.s_firstkernzone) << (1 + supb.s_zone_shift);
  334.     if (sect_aligned < sect_reserved)
  335.         sect_reserved = sect_aligned;
  336.     start_sect =supb.s_firstkernzone << (1 + supb.s_zone_shift);
  337.     }
  338.     sect_aligned = put_image(start_sect, sect_reserved);
  339.     if (!is_floppy)
  340.         start_sect += part_tab[rdev].start_sect;
  341.     put_super_block(start_sect, sect_aligned);
  342. }
  343.  
  344.  
  345. void inst_pri_boot()
  346. {
  347.     int dev_fd;
  348.     int i, j;
  349.     char * cp;
  350.  
  351.     fprintf(stderr, 
  352.         "\nThe master booter will be installed \n"
  353.         "in the first sector of %s.\n\n", 
  354.         blk_dev_name);
  355.     if ( !confirm() )
  356.         die("installing master booter aborted\n\n");
  357.  
  358.     if ((dev_fd = open(blk_dev_name, O_RDWR)) < 0)
  359.         die("open disk device `%s' failed", blk_dev_name);
  360.     if ( read(dev_fd, &super_buf, 512) != 512 )
  361.         die("read `%s' failed", blk_dev_name);
  362.  
  363.     memcpy(&super_buf, pritext, PRITEXTSIZE);
  364.     for (i=0; i < os_nr; i++) {
  365.         cp = os_name[i];
  366.         for (j=0; cp[j] && j < 15; j++)
  367.         master.os[i].os_name[j] = cp[j];
  368.     for (; j < 15; j++)
  369.         master.os[i].os_name[j] = ' ';
  370.     master.os[i].part_nr = os_part[i];
  371.     }
  372.     for (; i < 4; i++) {
  373.         for (j=0; j < 15; j++)
  374.         master.os[i].os_name[j] = ' ';
  375.     master.os[i].part_nr = 0;
  376.     }
  377.  
  378.     if ( lseek(dev_fd, 0, SEEK_SET) != 0 )
  379.         die("seek `%s' failed", blk_dev_name);
  380.     if ( write(dev_fd, &super_buf, 512) != 512)
  381.         die("write `%s' failed", blk_dev_name);
  382.  
  383.     close(dev_fd);
  384. }
  385.  
  386.  
  387. void rest_pri_boot()
  388. {
  389.     int fd;
  390.     int i;
  391.     
  392.     if ((fd = open(blk_dev_name, O_RDWR)) < 0)
  393.         die("open `%s' failed", blk_dev_name);
  394.     if (read(fd, buf, 512) != 512)
  395.         die("read `%s' failed", blk_dev_name);
  396.     for (i=0; i < ORGTEXTSIZE; i++)
  397.         buf[i]=orgtext[i];
  398.     if (lseek(fd, 0, SEEK_SET) != 0)
  399.         die("seek `%s' failed", blk_dev_name);
  400.     if (write(fd, buf, 512) != 512)
  401.         die("write `%s' failed", blk_dev_name);
  402.     close(fd);
  403. }
  404.  
  405. void main(int argc, char *argv[])
  406. {
  407.  
  408.     pgm_name=argv[0];
  409.  
  410.     if (getuid())
  411.         die("this program can only be run by the super-user");
  412.  
  413.     parse_arg(argc, argv);
  414.  
  415.     switch(action) {
  416.     case INST_SEC_BOOT: inst_sec_boot(); break;
  417.     case INST_PRI_BOOT: inst_pri_boot(); break;
  418.     case REST_PRI_BOOT: rest_pri_boot(); break;
  419.     }
  420.  
  421.     exit(0);
  422. }
  423.